import { defineComponent, defineAsyncComponent, resolveComponent, nextTick } from 'vue';
import UIBuilderRT from '../../../jsruntime/VUE/js/UIBuilderRT.mjs';
import DefaultElementEditor from './DefaultElementEditor.mjs';
let iconMap = {
    layer: 'ivu-icon ivu-icon-md-albums',
}
function elementListIcon(element) {
    return iconMap[element.type];
}
let UIBuilder = defineAsyncComponent(async () => {
    return {
        template: (await axios('./components/UIBuilder/UIBuilder.html')).data,
        components: { UIBuilderRT, DefaultElementEditor },
        data() {
            return {
                enabled: false,
                data: {
                    pages: [],
                },
                currentPage: null,
                showPageList: false,
                pageContextMenuFor: null,
                layerContainerDragging: null,
                selectedElement: null,
                contextMenuSelectedElement: null,
                pointingElement: null,
                //
                isShiftPressed: false,
            }
        },
        watch: {
            enabled(v, v1) {
                if (v) {

                } else {
                    OB_IDE.removeComponent(this);
                }
            },
        },
        beforeMount() {
            if (this.data.pages.length === 0) {
                this.addPage();
            }
            this.currentPage = this.data.pages[0];
            this.selectedElement = this.currentPage.tree[0];
        },
        mounted() {
            // document.addEventListener('keydown', this.handleKeyDown);
            // document.addEventListener('keyup', this.handleKeyUp);
            setTimeout(() => {
                this.zoom('showAllLayers');
            }, 1000);
        },
        beforeUnmount() {
            // document.removeEventListener('keydown', this.handleKeyDown);
            // document.removeEventListener('keyup', this.handleKeyUp);
        },
        computed: {
            isLandscape() {
                return this.currentPage.viewWidth > this.currentPage.viewHeight;
            },
        },
        watch: {
            'currentPage.dragState': {
                deep: true,
                handler(v) {
                    this.updateLayerContainerStyle();
                }
            },
            'currentPage.scale': {
                handler(v) {
                    this.updateLayerContainerStyle();
                }
            },
            'currentPage.viewWidth': {
                handler(v) {
                    this.updateLayerContainerStyle();
                }
            },
            'currentPage.viewHeight': {
                handler(v) {
                    this.updateLayerContainerStyle();
                }
            }
        },
        methods: {
            makeID() {
                let id;
                do {
                    id = OpenBlock.Utils.makeSN();
                } while (this.currentPage.__index[id]);
                return id;
            },
            addIndex(e) {
                if (this.currentPage.__index[e.id]) {
                    throw Error('重复ID');
                }
                this.currentPage.__index[e.id] = e;
                // let t = this.currentPage.tree;
                // this.currentPage.tree = null;
                // this.currentPage.tree = t;
            },
            createPage() {
                let width = 750;
                let height = 1280;
                return {
                    name: this.$t('页面' + this.data.pages.length),
                    tree: [],
                    id: OpenBlock.Utils.makeSN(),
                    layerContainerStyle: {
                        transform: 'translate(0, 0) scale(1)',
                        width: (width + 10) * 5 + 'px',
                        height: (height + 10) * 5 + 'px'
                    },
                    dragState: { x: 0, y: 0 },
                    scale: 1,
                    viewWidth: width,
                    viewHeight: height,
                    __index: {}
                };
            },
            createLayer(name) {
                return {
                    id: this.makeID(),
                    type: 'layer',
                    elementType: 'div',
                    isContainer: true,
                    style: { x: 0, y: 0, },
                    title: name,
                    expand: true,
                    selected: false,
                    contextmenu: true,
                    children: [],
                };
            },
            createContainer(__parent) {
                return {
                    id: this.makeID(),
                    type: 'container',
                    elementType: 'div',
                    isContainer: true,
                    style: { x: '0px', y: '0px', },
                    title: this.$t('容器'),
                    expand: true,
                    selected: false,
                    contextmenu: true,
                    children: [],
                    __parent,
                };
            },
            addPage() {
                let p = this.createPage();
                this.data.pages.push(p);
                this.currentPage = p;
                this.addLayer();
                return p;
            },
            addContainer() {
                let parent = this.selectedElement;
                if (!parent.isContainer) {
                    this.$Message.error(this.$t('无法在非容器内添加元素'));
                    return;
                }
                let c = this.createContainer(parent);
                this.addIndex(c);
                parent.children.push(c);
            },
            addLayer() {
                let l = this.createLayer(this.$t('图层' + (this.currentPage.tree.length)));
                this.addIndex(l);
                this.currentPage.tree.push(l);
                this.selectedElement = l;
            },
            updateLayerContainerStyle() {
                this.currentPage.layerContainerStyle = {
                    transform: `translate(${parseInt(this.currentPage.dragState.x + 20 / this.currentPage.scale)}px, ${parseInt(this.currentPage.dragState.y + 20 / this.currentPage.scale)}px) scale(${this.currentPage.scale})`,
                    width: this.currentPage.viewWidth * this.currentPage.scale * 5.5 + 'px',
                };
            },
            showLayerContextMenu(event, layer) {
                this.contextMenuSelectedElement = layer;
                nextTick(() => {
                    let rect = this.$refs.layerContainer.getBoundingClientRect();
                    this.$refs.layerContextMenu.style.left = `${event.pageX}px`;
                    this.$refs.layerContextMenu.style.top = `${event.pageY}px`;
                });
            },
            showPageContextMenu(event, page) {
                this.pageContextMenuFor = page;
                nextTick(() => {
                    this.$refs.pageContextMenu.style.left = `${event.pageX}px`;
                    this.$refs.pageContextMenu.style.top = `${event.pageY}px`;
                });
            },
            async renamePage(page) {
                console.log('renamePage', page);
                let name = await OB_IDE.asyncPrompt(this.$t('请输入新名称'), page.name);
                if (name) {
                    if (OpenBlock.Utils.isIdentifier(name)) {
                        page.name = name;
                    } else {
                        OB_IDE.$Message.error(this.$t('名称不能数字开始，且不能包含特殊字符'));
                        this.renamePage(page);
                    }
                }
            },
            layerContainerDragStart: function (event) {
                if (event.button !== 1) {
                    return;
                }
                this.layerContainerDragging = {
                    startX: event.pageX - this.currentPage.dragState.x,
                    startY: event.pageY - this.currentPage.dragState.y,
                };
            },
            coordinateOfLayerContainer(event) {
                let rect = this.$refs.layerContainer.getBoundingClientRect();
                return { x: event.pageX - rect.left, y: event.pageY - rect.top };
            },
            layerContainerMouseMove: function (event) {
                if (this.layerContainerDragging) {
                    this.currentPage.dragState.x = event.pageX - this.layerContainerDragging.startX;
                    this.currentPage.dragState.y = event.pageY - this.layerContainerDragging.startY;
                }
                this.pointingElement = event.target;
                // console.log('container', this.coordinateOfLayerContainer(event));
            },
            layerContainerDragEnd: function () {
                this.layerContainerDragging = null;
            },
            layerContainerWheel(event) {
                if (event.shiftKey) {
                    this.currentPage.dragState.x -= event.deltaY;
                    this.currentPage.dragState.y -= event.deltaX;
                    return;
                } else if (event.ctrlKey) {
                    event.preventDefault(); // 阻止默认行为，避免页面滚动 
                    this.zoom(event.deltaY < 0 ? 'zoomIn' : 'zoomOut', event);
                    return;
                } else {
                    this.currentPage.dragState.y -= event.deltaY;
                    this.currentPage.dragState.x -= event.deltaX;
                }
            },
            layerNameStyle(layer, i) {

            },
            layerStyle(layer, i) {
                return {
                    width: this.currentPage.viewWidth + 'px',
                    height: this.currentPage.viewHeight + 'px',
                    // display: 'flex'
                    // border: this.pointingElement?.id === layer.id ? '1px solid blue' : '1px solid #0005',
                }
            },
            layerClass(layer, i) {
                return ['rootLayer'
                    //,
                    // this.pointingElement?.id === layer.id ? 'pointing' : '',
                    // this.selectedElement?.id === layer.id ? 'selected' : '',
                ]
            },
            zoomAt(node) {
                let element = document.getElementById(node.id);
                if (!element) return;
                if (Array.isArray(element)) {
                    element = element[0];
                }
                let rect = element.getBoundingClientRect();
                // let layerContainerRect = this.$refs.uidesignLayoutContent.getBoundingClientRect();
                let centerX = rect.left + rect.width / 2;
                let centerY = rect.top + rect.height / 2;
                let moveX = centerX - window.innerWidth / 2;
                let moveY = centerY - window.innerHeight / 2;
                this.currentPage.dragState.x -= moveX;
                this.currentPage.dragState.y -= moveY;
                // this.currentPage.dragState.x = this.currentPage.scale * (layerContainerRect.left + layerContainerRect.width / 2) - centerX;
                // this.currentPage.dragState.y = (layerContainerRect.top + layerContainerRect.height / 2) * this.currentPage.scale - centerY;
                // this.zoom(null,{pageX: centerX, pageY: centerY});
            },
            zoom(name, event) {
                let uidesignLayoutContentRect = this.$refs.uidesignLayoutContent.getBoundingClientRect();
                let width = uidesignLayoutContentRect.width;
                if (name == 'showAllLayers') {
                    this.currentPage.scale = width / this.currentPage.viewWidth / this.currentPage.tree.length * 0.9;
                    this.currentPage.dragState.y = 0;
                    this.currentPage.dragState.x = 0;
                    return;
                }
                let layerContainerRect = this.$refs.layerContainer.getBoundingClientRect();
                let s = this.currentPage.scale;
                let targetPoint;
                if (event) {
                    targetPoint = {
                        x: event.pageX,
                        y: event.pageY
                    }
                } else {
                    targetPoint = {
                        x: window.innerWidth / 2,
                        y: window.innerHeight / 2
                    }
                }
                targetPoint.x -= layerContainerRect.left;
                targetPoint.y -= layerContainerRect.top;
                if (typeof (name) == 'number') {
                    this.currentPage.scale = name;
                } else switch (name) {
                    case 'zoomIn':
                        this.currentPage.scale = parseFloat((this.currentPage.scale / 0.75).toFixed(2));
                        break;
                    case 'zoomOut':
                        this.currentPage.scale = parseFloat((this.currentPage.scale * 0.75).toFixed(2));
                        break;
                    case 'zoomToFitWidth':
                        this.currentPage.scale = width / this.currentPage.viewWidth * 0.99;
                        break;
                    case 'zoomToFitHeight':
                        let height = uidesignLayoutContentRect.height;
                        this.currentPage.scale = height / this.currentPage.viewHeight * 0.99;
                        break;
                    case '50%':
                        this.currentPage.scale = 0.5;
                        break;
                    case '100%':
                        this.currentPage.scale = 1;
                        break;
                    case '150%':
                        this.currentPage.scale = 1.5;
                        break;
                    case '200%':
                        this.currentPage.scale = 2;
                        break;
                }
                let endPont = {
                    x: targetPoint.x * this.currentPage.scale / s - targetPoint.x,
                    y: targetPoint.y * this.currentPage.scale / s - targetPoint.y
                }
                this.currentPage.dragState.x -= endPont.x;
                this.currentPage.dragState.y -= endPont.y;
            },
            handleKeyDown(event) {
                if (event.key === 'Shift') {
                    this.isShiftPressed = event.keyCode;
                }
            },
            handleKeyUp(event) {
                if (event.keyCode === this.isShiftPressed) {
                    this.isShiftPressed = false;
                }
            },
            handleContentContentContextMenu(data, event, position) {
                this.contextMenuSelectedElement = data;
            },
            async renameContent() {
                let name = await OB_IDE.asyncPrompt(this.$t('请输入新名称'), this.contextMenuSelectedElement.title);
                if (name) {
                    this.contextMenuSelectedElement.title = name;
                }
            },
            async addToTemplate() { },
            async changePage(page) {
                this.currentPage = page;
                this.selectedElement = null;
            },
            async deleteContent() {
                if (this.contextMenuSelectedElement) {
                    if (this.contextMenuSelectedElement.type == 'layer') {
                        this.currentPage.tree = this.currentPage.tree.filter(item => item !== this.contextMenuSelectedElement);
                    } else {
                        let index = this.contextMenuSelectedElement.__parent.children.findIndex(item => item === this.contextMenuSelectedElement);
                        if (index > -1) {
                            this.contextMenuSelectedElement.__parent.children.splice(index, 1);
                        }
                    }
                }
            },
            async save() {
                let data = this.$refs.editor.getValue();
                if (data) {
                    await OpenBlock.saveSrc(data);
                }
            },
            layerMouseMove(event) {
                this.pointingElement = event.target;
                // console.log('layer', event.offsetX / this.currentPage.scale, event.offsetY / this.currentPage.scale);
            },
            layerMouseOut(event) {
                if (this.pointingElement === event.target) {
                    this.pointingElement = null;
                }
            },
            treeRender(h, { root, node, data }) {
                let that = this;
                return h(
                    'span',
                    {
                        class: 'ui-element-list-item-tree-node',
                        style: {
                        },
                    },
                    [
                        h('i', {
                            class: [
                                'chevron icon expandIcon',
                                data.expand ? "down" : "right"
                            ],
                            onclick: () => {
                                data.expand = !data.expand;
                            }
                        }),
                        h('span', {
                            class: ['ui-element-list-item',
                                that.selectedElement === data ? "selected" : ""],
                            onClick(event) {
                                that.selectedElement = data;
                            },
                            onDblclick(event) {
                                that.selectedElement = data;
                                that.zoomAt(data);
                            }
                        }, [
                            h('i', { class: [elementListIcon(data), 'typeIcon'] }),
                            , data.title])
                    ]
                );
            },
            RTOverride(node) {
                if (node == this.selectedElement) {
                    let attr = Object.assign({}, node.attr);
                    let border = { border: '1vw solid #b00000' };
                    attr.style = attr.style ? Object.assign(attr.style, border) : border;
                    return attr;
                }
            },
            onClickOnNode(node) {
                this.selectedElement = node;
            },
            canvasKeyDown(event) {
                if (event.key === '+') {
                    this.zoom('zoomIn');
                } else if (event.key === '-') {
                    this.zoom('zoomOut');
                }
            },
        }
    }
});
UIBuilder.open = async function (scene) {
    await OpenBlock.saveAllSrc();
    let closemsg;
    try {
        closemsg = OB_IDE.$Message.loading({
            content: OB_IDE.$t('正在编译'),
            duration: 0
        });
        // showOverallLoading();
        OB_IDE.closeSider();
        // OB_IDE.closeAllTabs();
        let buf = await OpenBlock.exportExePackage(scene);
        console.log('编译完成');
        let win = await OB_IDE.addComponent(UIBuilder);
        win.enabled = true;
    } catch (e) {
        OB_IDE.$Message.error(OB_IDE.$t('编译失败:') + e.message);
    } finally {
        // hideOverallLoading();
        closemsg();
    }
};
export default UIBuilder;